<script setup>
import { reactive, ref, onMounted, getCurrentInstance, nextTick, onUnmounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import MainContent from '@/components/mainContent.vue'

const { proxy: { $http } } = getCurrentInstance()
const route = useRoute()
const router = useRouter()

// WebSocket 配置
const ws = ref(null)
const isWsConnected = ref(false)
const reconnectTimer = ref(null)
const wsUrl = 'ws://192.168.1.19:9012/xjwxx-websocket';
const wsTopic = '/topic/school/student';

// 缓存核心配置（唯一键名，避免与其他功能冲突）
const CACHE_KEY = 'studentFeedback_PersistentData';
// 学生反馈数据（从缓存初始化，刷新后保留）
const feedbackList = ref([])
// 已提交人数（与数据列表同步）
const submittedCount = ref(0)

// -------------------------- 缓存核心方法 --------------------------
/**
 * 从 localStorage 读取缓存数据（确保刷新后恢复）
 * @returns {Array} 格式化后的反馈数据数组
 */
const loadCacheData = () => {
  try {
    // 1. 读取缓存（localStorage 存储的是字符串）
    const cachedStr = localStorage.getItem(CACHE_KEY);
    if (!cachedStr) return []; // 无缓存返回空数组

    // 2. 解析 JSON（防止格式错误）
    const cachedData = JSON.parse(cachedStr);

    // 3. 验证数据格式（必须是数组，且每个项有必填字段）
    if (!Array.isArray(cachedData)) {
      console.warn('缓存数据格式错误，已清空无效缓存');
      localStorage.removeItem(CACHE_KEY);
      return [];
    }

    // 4. 过滤无效数据（确保每个项有学号和图片）
    const validData = cachedData.filter(item =>
        item.id && item.mainImg && Array.isArray(item.subImgs)
    );

    console.log(`从缓存加载有效数据：${validData.length} 条`);
    return validData;
  } catch (error) {
    // 缓存损坏时清空，避免影响页面
    console.error('读取缓存失败：', error);
    localStorage.removeItem(CACHE_KEY);
    return [];
  }
};

/**
 * 将当前数据写入缓存（确保新数据实时保存）
 * @param {Array} data - 要缓存的学生反馈数据
 */
const saveToCache = (data) => {
  try {
    // 只缓存有效数据（避免存储空值/错误格式）
    const validData = data.filter(item =>
        item.id && item.mainImg && Array.isArray(item.subImgs)
    );
    const dataStr = JSON.stringify(validData);
    localStorage.setItem(CACHE_KEY, dataStr);
    console.log(`缓存已更新，当前共 ${validData.length} 条数据`);
  } catch (error) {
    console.error('写入缓存失败：', error);
  }
};

/**
 * 手动清空缓存（支持重置数据）
 */
const clearAllCache = () => {
  if (confirm('确定要清空所有历史反馈数据吗？此操作不可恢复！')) {
    localStorage.removeItem(CACHE_KEY);
    feedbackList.value = [];
    submittedCount.value = 0;
    alert('历史数据已清空');
  }
};
// ------------------------------------------------------------------

// WebSocket 初始化与消息处理
const initWebSocket = () => {
  if (ws.value && isWsConnected.value) return;
  try {
    ws.value = new WebSocket(wsUrl);

    // 连接成功：订阅主题
    ws.value.onopen = () => {
      isWsConnected.value = true;
      console.log('WebSocket 连接成功');
      sendSubscribeMsg();
    };

    // 接收消息：处理学生反馈数据
    ws.value.onmessage = (event) => {
      try {
        const msgData = JSON.parse(event.data);
        const feedbackData = msgData.data?.data?.content;
        // 只处理类型为 "img" 的有效反馈数据
        if (msgData.data?.type === 'commit' && msgData.data?.data?.type === 'img' && feedbackData) {
          handleNewFeedback(feedbackData);
        }
      } catch (error) {
        console.error('解析WebSocket消息失败：', error);
      }
    };

    // 连接错误：自动重连
    ws.value.onerror = (error) => {
      isWsConnected.value = false;
      console.error('WebSocket 错误：', error);
      triggerReconnect();
    };

    // 连接关闭：非主动关闭则重连
    ws.value.onclose = (event) => {
      isWsConnected.value = false;
      if (event.code !== 1000) {
        console.error(`WebSocket 意外关闭（状态码：${event.code}），3秒后重连`);
        triggerReconnect();
      }
    };
  } catch (error) {
    console.error('初始化WebSocket失败：', error);
  }
};

// 发送WebSocket订阅请求
const sendSubscribeMsg = () => {
  if (!ws.value || !isWsConnected.value) return;
  const subscribeMsg = {
    command: 'SUBSCRIBE',
    destination: wsTopic
  };
  ws.value.send(JSON.stringify(subscribeMsg));
  console.log('已订阅学生反馈主题：', wsTopic);
};

// 处理新收到的反馈数据（去重+更新缓存）
const handleNewFeedback = (rawData) => {
  const { student: studentId, images } = rawData;
  // 过滤无效数据（必须有学号和图片）
  if (!studentId || !images?.length) {
    console.warn('收到无效反馈数据：缺少学号或图片');
    return;
  }

  // 拆分图片：第一张为大图，剩余为小图
  const mainImg = images[0];
  const subImgs = images.slice(1);
  const currentTime = new Date().getTime();

  // 数据去重：同一学生只保留一条记录（更新现有数据）
  const existingIndex = feedbackList.value.findIndex(item => item.id === studentId);
  if (existingIndex > -1) {
    // 已存在：更新图片和时间
    feedbackList.value[existingIndex] = {
      ...feedbackList.value[existingIndex],
      mainImg,
      subImgs,
      count: images.length,
      updateTime: currentTime // 记录最后更新时间
    };
  } else {
    // 不存在：新增记录
    feedbackList.value.push({
      id: studentId,
      mainImg,
      subImgs,
      count: images.length,
      createTime: currentTime, // 记录创建时间
      updateTime: currentTime
    });
  }

  // 更新已提交人数
  submittedCount.value = feedbackList.value.length;
  // 关键：更新缓存（确保刷新后数据不消失）
  saveToCache(feedbackList.value);
};

// WebSocket 自动重连
const triggerReconnect = () => {
  if (reconnectTimer.value) clearTimeout(reconnectTimer.value);
  reconnectTimer.value = setTimeout(initWebSocket, 3000);
};

// 页面挂载：优先加载缓存 → 再初始化WebSocket
onMounted(async () => {
  // 1. 第一步：加载缓存数据（确保刷新后先显示历史记录）
  const cachedData = loadCacheData();
  if (cachedData.length > 0) {
    feedbackList.value = cachedData;
    submittedCount.value = cachedData.length;
  }

  // 2. 第二步：初始化WebSocket（接收新数据）
  initWebSocket();
  await nextTick();
});

// 页面卸载：确保最后一条数据写入缓存
onUnmounted(() => {
  // 1. 断开WebSocket连接
  if (ws.value) {
    ws.value.close(1000, '页面关闭，主动断开');
    ws.value = null;
  }
  // 2. 清除重连定时器
  if (reconnectTimer.value) {
    clearTimeout(reconnectTimer.value);
  }
  // 3. 兜底：最后一次更新缓存（防止遗漏）
  saveToCache(feedbackList.value);
});
</script>

<template>
  <MainContent contentWidth="90%" bgColor="#ffffff" padding="24px">
    <template #content>
      <div class="content-layout">
        <!-- 顶部固定栏：已提交人数+标题+倒计时+清空缓存 -->
        <div class="top-bar">
          <div class="submitted">已提交 <span class="count">{{ submittedCount }}</span> 人</div>
          <button class="clear-cache-btn" @click="clearAllCache">清空历史数据</button>
          <div class="title-wrapper">
            <span class="line"></span>
            <span class="title">学生反馈</span>
            <span class="line"></span>
          </div>
          <div class="countdown">倒计时：<span class="time">300s</span></div>
        </div>

        <!-- 卡片滚动容器：缓存数据+新数据都会显示 -->
        <div class="card-container">
          <div class="card-grid">
            <!-- 无数据提示（缓存和新数据都为空时显示） -->
            <div class="empty-tip" v-if="feedbackList.length === 0">
              暂无学生反馈数据
            </div>

            <!-- 反馈卡片：循环渲染缓存+新数据 -->
            <div class="feedback-card" v-for="item in feedbackList" :key="item.id">
              <!-- 主图（第一张图片） -->
              <img
                  :src="item.mainImg"
                  alt="学生反馈主图"
                  class="main-img"
                  loading="lazy"
                  @error="(e) => e.target.src = 'https://picsum.photos/200/150?fallback'"
              />
              <!-- 子图（剩余图片，无则不显示） -->
              <div class="sub-imgs" v-if="item.subImgs.length">
                <img
                    v-for="(subImg, idx) in item.subImgs"
                    :key="idx"
                    :src="subImg"
                    alt="反馈子图"
                    class="sub-img"
                    loading="lazy"
                    @error="(e) => e.target.src = 'https://picsum.photos/60/40?fallback'"
                />
              </div>
              <!-- 卡片底部：学号+图片数+时间 -->
              <div class="card-footer">
                <span class="student-id">学号：{{ item.id }}</span>
                <span class="img-count">共{{ item.count }}张</span>
                <span class="update-time">
                  更新时间：{{ new Date(item.updateTime).toLocaleString() }}
                </span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>
  </MainContent>
</template>

<style scoped lang='scss'>
// 基础重置
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

// 核心布局容器（不承担滚动）
.content-layout {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: calc(100vh - 180px);
  border-radius: 16px;
  padding: 20px;

  // 平板适配
  @media (min-width: 768px) and (max-width: 1024px) {
    padding: 25px;
    max-height: calc(100vh - 200px);
  }

  // 电脑适配
  @media (min-width: 1024px) {
    padding: 30px;
    max-height: calc(100vh - 220px);
  }
}

// 顶部固定栏（刷新后仍固定在顶部）
.top-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 15px;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 2px 6px rgba(0,0,0,0.05);
  flex-wrap: wrap;
  gap: 10px;
  position: sticky;
  top: 0;
  z-index: 10;

  // 小屏手机适配
  @media (max-width: 375px) {
    justify-content: center;
    padding: 8px 10px;
  }
}

// 清空缓存按钮
.clear-cache-btn {
  padding: 4px 10px;
  border: 1px solid #e63946;
  border-radius: 4px;
  background: transparent;
  color: #e63946;
  font-size: 12px;
  cursor: pointer;
  transition: all 0.2s;

  &:hover {
    background: #e63946;
    color: #fff;
  }

  // 小屏隐藏，避免拥挤
  @media (max-width: 375px) {
    display: none;
  }
}

// 已提交人数和倒计时
.top-bar .submitted,
.top-bar .countdown {
  color: #333;
  font-size: 14px;

  @media (max-width: 375px) {
    font-size: 12px;
  }
}

// 强调色（已提交人数数字、倒计时）
.top-bar .count,
.top-bar .time {
  color: #e63946;
  font-weight: bold;
}

// 标题左右横线
.title-wrapper {
  display: flex;
  align-items: center;
  min-width: 150px;

  .line {
    flex: 1;
    height: 1px;
    background: #ccc;
    margin: 0 8px;

    @media (min-width: 1024px) {
      margin: 0 12px;
    }
  }

  .title {
    font-size: 18px;
    font-weight: bold;
    color: #e63946;

    @media (min-width: 1024px) {
      font-size: 20px;
    }
  }
}

// 卡片滚动容器（仅卡片区域滚动）
.card-container {
  flex: 1;
  overflow-y: auto;
  border-radius: 8px;

  // 自定义滚动条（保持半透明无背景）
  &::-webkit-scrollbar {
    width: 6px;
  }
  &::-webkit-scrollbar-track {
    background: transparent;
  }
  &::-webkit-scrollbar-thumb {
    background: rgba(220,220,220,0.5);
    border-radius: 3px;
  }
  &::-webkit-scrollbar-thumb:hover {
    background: rgba(200,200,200,0.6);
  }
  &::-webkit-scrollbar-button {
    display: none;
  }
}

// 卡片网格（自适应列数）
.card-grid {
  padding: 20px;
  border-radius: 10px;
  background: #fff;
  display: grid;
  grid-template-columns: 1fr;
  gap: 15px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.2);

  // 小屏手机（2列）
  @media (min-width: 375px) {
    grid-template-columns: repeat(2, 1fr);
  }

  // 平板（3列）
  @media (min-width: 480px) {
    grid-template-columns: repeat(3, 1fr);
  }

  // 平板横屏/小电脑（4列）
  @media (min-width: 768px) {
    grid-template-columns: repeat(4, 1fr);
    gap: 18px;
  }

  // 电脑（5列）
  @media (min-width: 1024px) {
    grid-template-columns: repeat(5, 1fr);
    gap: 20px;
  }
}

// 无数据提示
.empty-tip {
  grid-column: 1 / -1;
  text-align: center;
  padding: 60px 0;
  color: #999;
  font-size: 16px;
}

// 反馈卡片
.feedback-card {
  border-radius: 10px;
  width: 100%;
  background: #f1f5f6;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 15px 0;
}

// 卡片主图
.main-img {
  width: 85%;
  height: 100px;
  object-fit: cover;
  border-radius: 12px;
  padding: 8px;

  @media (min-width: 1024px) {
    height: 120px;
    padding: 10px;
    border-radius: 16px;
  }
}

// 卡片子图容器
.sub-imgs {
  display: flex;
  gap: 6px;
  padding: 0 10px;

  @media (min-width: 1024px) {
    gap: 10px;
  }
}

// 卡片子图
.sub-img {
  width: 35px;
  height: 25px;
  object-fit: cover;
  border-radius: 2px;

  @media (min-width: 1024px) {
    width: 40px;
    height: 30px;
  }
}

// 卡片底部信息
.card-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  width: 85%;
  padding: 0 8px;
  font-size: 12px;
  color: #666;
  gap: 5px;

  @media (min-width: 1024px) {
    font-size: 13px;
  }

  .update-time {
    width: 100%;
    text-align: right;
    color: #999;
    font-size: 11px;
  }
}

// 冗余样式清理
.content-divider,
.content-image,
.book-card {
  display: none;
}

// 小屏内边距适配
@media (max-width: 375px) {
  .main-content {
    padding: 12px;
  }
}
</style>
